package com.sd.repay.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.sd.repay.common.CommonResult;
import com.sd.repay.common.Constants;
import com.sd.repay.dao.BaseDao;
import com.sd.repay.pojo.MerchantUser;
import com.sd.repay.service.*;
import com.sd.repay.utils.JsonUtil;
import com.sd.repay.utils.StringUtil;
import com.sd.repay.utils.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by sd on 2018/08/21
 * 商户服务类
 */
@Service
public class MerchantServiceImpl implements MerchantService {

    public final static Logger log = LoggerFactory.getLogger(MerchantServiceImpl.class);

    @Autowired
    private BaseDao baseDao;
    @Autowired
    private AgentService agentService;
    @Autowired
    private ActivateService activateService;
    @Autowired
    private MerFeeService merFeeService;
    @Autowired
    private RankService rankService;

    /**
     * 根据商户号获取商户信息
     *
     * @param merchantNo
     * @return
     */
    @Override
    public Map<String, Object> getMerInfoByMerNo(String merchantNo) {

        String sql = " SELECT * FROM t_merchant_info WHERE merchant_no = ? ";
        return baseDao.findFirst(sql, merchantNo);
    }

    /**
     * 保存商户信息
     *
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int addMerchantInfo(Map<String, String> map) throws Exception {

        String merchantNo = map.get("merchantNo");
        String mobileNo = map.get("mobileNo");
        String oemType = map.get("oemType");
        //新增商户为默认等级
        String rankCode = Constants.RANK_CODE_SILVER;
        //获取全局分销开关
        String wholeDistribSwitch = WebUtil.getSysValue("WHOLE_DISTRIB_SWITCH");
        log.info("系统配置全局分销开关【{}】", wholeDistribSwitch);
        wholeDistribSwitch = StringUtils.isBlank(wholeDistribSwitch) ? Constants.WHOLE_DISTRIB_SWITCH_OPEN : wholeDistribSwitch;

        String sql = " INSERT INTO t_merchant_info(oem_type,merchant_no,merchant_name,mobile_no,login_pwd,province,city,address,email,link_man,sale_name,parent_mer_no," +
                "mer_grade,mer_node,agent_no,one_agent_no,agent_node,rank_code,status,trade_distrib_switch,withdraw_distrib_switch,create_time) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        List<Object> params = new ArrayList<>();
        params.add(oemType);
        params.add(merchantNo);
        params.add(map.get("merchantName"));
        params.add(mobileNo);
        params.add(map.get("loginPwd"));
        params.add(map.get("province"));
        params.add(map.get("city"));
        params.add(map.get("address"));
        params.add(map.get("email"));
        params.add(map.get("linkMan"));
        params.add(map.get("saleName"));
        params.add(map.get("parentMerNo"));
        params.add(map.get("merGrade"));
        params.add(map.get("merNode"));
        params.add(map.get("agentNo"));
        params.add(map.get("oneAgentNo"));
        params.add(map.get("agentNode"));
        params.add(rankCode);
        params.add(Constants.MERCHANT_STATUS_SUCCESS);
        params.add(wholeDistribSwitch);
        params.add(wholeDistribSwitch);
        params.add(new Date());
        int count = baseDao.execute(sql, params.toArray());
        if (count > 0) {

            //通过激活码注册的商户需要激活激活码
            String activateCode = map.get("activateCode");
            if (StringUtils.isNotBlank(activateCode)) {
                count = activateService.activateCode(merchantNo, activateCode);
                log.info("用户手机号{}注册后生成商户号{}激活码{}激活影响的行数{}", new Object[]{mobileNo, merchantNo, activateCode, count});
                if (count < 1) {
                    throw new RuntimeException("激活码" + activateCode + "激活失败");
                }

            } else {
                //通过分享注册的商户，需要判断上级商户是否达到提升等级的分享数量
                String parentMerNo = map.get("parentMerNo");
                Map<String, Object> parentMerInfo = getMerInfoByMerNo(parentMerNo);
                String parentMerRankCode = StringUtil.filterNull(parentMerInfo.get("rank_code"));

                //获取所有直属下级
                List<Map<String, Object>> subMerList = getSubMerchant(oemType, parentMerNo);
                int subMerNum = subMerList.size();
                log.info("新增商户[{}]上级商户[{}]当前所有直接子商户数量[{}]", new Object[]{mobileNo, parentMerNo, subMerNum});

                String toMerRanCode = "";
                switch (parentMerRankCode) {
                    case Constants.RANK_CODE_SILVER: {
                        toMerRanCode = Constants.RANK_CODE_GOLD;
                        break;
                    }
                    case Constants.RANK_CODE_GOLD: {
                        toMerRanCode = Constants.RANK_CODE_PLATINUM;
                        break;
                    }
                    case Constants.RANK_CODE_PLATINUM: {
                        toMerRanCode = Constants.RANK_CODE_DIAMONDS;
                        break;
                    }
                    case Constants.RANK_CODE_DIAMONDS: {
                        break;
                    }
                }
                if (StringUtils.isNotBlank(toMerRanCode)) {
                    String promoteMerNum = rankService.getRankConfigByOemAndCodeAndService(oemType, toMerRanCode, Constants.RANK_SERVICE_SHARE_MER_NUM);
                    log.info("系统配置等级[{}]需要分享的商户数量[{}]", new Object[]{toMerRanCode, promoteMerNum});
                    if (subMerNum == Integer.parseInt(promoteMerNum)) {
                        log.info("新增商户[{}]上级商户[{}]达到提升等级[{}]的分享商户数量[{}]", new Object[]{mobileNo, parentMerNo, toMerRanCode, promoteMerNum});
                        CommonResult promoteRes = promoteMerRankInfo(parentMerNo, toMerRanCode);
                        if (promoteRes.getStatus() != 200) {
                            throw new RuntimeException("新增商户" + mobileNo + "提升上级商户" + parentMerNo + "等级至" + toMerRanCode + "失败");
                        }
                    }
                }
            }

            //新增商户费率
            String quickRepayValue = rankService.getRankConfigByOemAndCodeAndService(oemType, rankCode, Constants.RANK_SERVICE_QUICK_FEE);
            String perfectRepayValue = rankService.getRankConfigByOemAndCodeAndService(oemType, rankCode, Constants.RANK_SERVICE_PERFECT_FEE);
            String withdrawValue = rankService.getRankConfigByOemAndCodeAndService(oemType, rankCode, Constants.RANK_SERVICE_SINGLE_WITHDRAW);

            Map<String, String> merFeeInfo = new HashMap<>();
            merFeeInfo.put("oemType", oemType);
            merFeeInfo.put("merType", Constants.MER_TYPE_MERCHANT);
            merFeeInfo.put("merNo", merchantNo);
            merFeeInfo.put("quickFeeRate", quickRepayValue.split("\\+")[0]);
            merFeeInfo.put("quickSingleFee", quickRepayValue.split("\\+")[1]);
            merFeeInfo.put("perfectFeeRate", perfectRepayValue.split("\\+")[0]);
            merFeeInfo.put("perfectSingleFee", perfectRepayValue.split("\\+")[1]);
            merFeeInfo.put("withdrawFeeRate", withdrawValue.split("\\+")[0]);
            merFeeInfo.put("withdrawSingleFee", withdrawValue.split("\\+")[1]);

            count = merFeeService.saveMerFeeInfo(merFeeInfo);
            log.info("商户手机号：{}注册商户：{}设置费率信息影响的行数：{}", new Object[]{mobileNo, merchantNo, count});
            if (count < 1) {
                throw new RuntimeException("商户手机号：" + mobileNo + "设置费率信息失败");
            }
        }
        return count;
    }

    /**
     * 修改用户等级
     *
     * @param merchantNo
     * @param oldMerRank
     * @param newMerRank
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int updateMerRank(String merchantNo, String oldMerRank, String newMerRank) throws Exception {

        String sql = " UPDATE t_merchant_info SET rank_code = ? WHERE merchant_no = ? AND rank_code = ? ";
        return baseDao.execute(sql, new Object[]{newMerRank, merchantNo, oldMerRank});
    }

    /**
     * 提升用户等级信息
     *
     * @param merchantNo
     * @param toRankCode 为空默认向上提升一个等级
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public CommonResult promoteMerRankInfo(String merchantNo, String toRankCode) throws Exception {

        if (StringUtils.isBlank(merchantNo)) {
            return CommonResult.build(403, "商户号不能为空");
        }
        //获取商户信息
        Map<String, Object> merInfoMap = getMerInfoByMerNo(merchantNo);
        log.info("提升商户号[{}]等级对应的原始商户信息[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(merInfoMap)});
        if (merInfoMap == null || merInfoMap.isEmpty()) {
            return CommonResult.build(403, "商户信息不存在");
        }
        String oemType = StringUtil.filterNull(merInfoMap.get("oem_type"));
        String origRankCode = StringUtil.filterNull(merInfoMap.get("rank_code"));
        if (StringUtils.isBlank(origRankCode)) {
            log.info("提升商户号[{}]等级对应的原始等级为空", new Object[]{merchantNo});
            return CommonResult.build(403, "原始商户等级为空");
        }
        if (StringUtils.isBlank(toRankCode)) {
            switch (origRankCode) {
                case Constants.RANK_CODE_SILVER: {
                    toRankCode = Constants.RANK_CODE_GOLD;
                    break;
                }
                case Constants.RANK_CODE_GOLD: {
                    toRankCode = Constants.RANK_CODE_PLATINUM;
                    break;
                }
                case Constants.RANK_CODE_PLATINUM: {
                    toRankCode = Constants.RANK_CODE_DIAMONDS;
                    break;
                }
                case Constants.RANK_CODE_DIAMONDS: {
                    return CommonResult.build(403, "已是最顶级商户");
                }
            }
        }
        if (!Constants.RANK_CODE_SILVER.equals(toRankCode) && !Constants.RANK_CODE_GOLD.equals(toRankCode) && !Constants.RANK_CODE_PLATINUM.equals(toRankCode)
                && !Constants.RANK_CODE_DIAMONDS.equals(toRankCode)) {
            return CommonResult.build(403, "等级不合法");
        }

        //获取新等级对应的信息
        String newQuickFee = rankService.getRankConfigByOemAndCodeAndService(oemType, toRankCode, Constants.RANK_SERVICE_QUICK_FEE);
        String newPerfectFee = rankService.getRankConfigByOemAndCodeAndService(oemType, toRankCode, Constants.RANK_SERVICE_PERFECT_FEE);
        String newSingleWithdraw = rankService.getRankConfigByOemAndCodeAndService(oemType, toRankCode, Constants.RANK_SERVICE_SINGLE_WITHDRAW);
        log.info("提升商户号[{}]等级至[{}]对应的费率及成本信息分别为[{}],[{}],[{}]", new Object[]{merchantNo, toRankCode, newQuickFee, newPerfectFee, newSingleWithdraw});

        if (StringUtil.isBlank(newQuickFee, newPerfectFee, newSingleWithdraw)) {
            return CommonResult.build(403, "等级配置有误，请稍候再试");
        }
        if (newQuickFee.split("\\+").length != 2 || newPerfectFee.split("\\+").length != 2 || newSingleWithdraw.split("\\+").length != 2) {
            return CommonResult.build(403, "等级配置有误，请稍候再试");
        }

        //获取商户原始费率信息
        Map<String, Object> merFeeMap = merFeeService.getMerFeeByMerNoAndOemType(Constants.MER_TYPE_MERCHANT, merchantNo, oemType);
        log.info("提升商户号[{}]原始服务信息为[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(merFeeMap)});
        if (merFeeMap == null || merFeeMap.isEmpty()) {
            return CommonResult.build(403, "商户原始服务信息为空");
        }

        Map<String, String> updateParams = new HashMap<>();
        updateParams.put("quickFeeRate", newQuickFee.split("\\+")[0]);
        updateParams.put("quickSingleFee", newQuickFee.split("\\+")[1]);
        updateParams.put("perfectFeeRate", newPerfectFee.split("\\+")[0]);
        updateParams.put("perfectSingleFee", newPerfectFee.split("\\+")[1]);
        updateParams.put("withdrawFeeRate", newSingleWithdraw.split("\\+")[0]);
        updateParams.put("withdrawSingleFee", newSingleWithdraw.split("\\+")[1]);
        updateParams.put("merType", Constants.MER_TYPE_MERCHANT);
        updateParams.put("merNo", merchantNo);

        int count = merFeeService.updateMerFeeInfo(updateParams);
        log.info("提升商户号[{}]等级至[{}]修改商户服务影响的行数", new Object[]{merchantNo, toRankCode, count});
        if (count < 1) {
            return CommonResult.build(403, "提升等级失败，请稍后再试");
        }

        count = updateMerRank(merchantNo, origRankCode, toRankCode);
        log.info("提升商户号[{}]等级至[{}]影响的行数", new Object[]{merchantNo, toRankCode, count});
        if (count < 1) {
            throw new RuntimeException("修改商户等级失败");
        }
        return CommonResult.ok();
    }

    /**
     * 根据手机号和OEM获取商户信息
     *
     * @param mobileNo
     * @param oemType
     * @return
     */
    @Override
    public Map<String, Object> getMerInfoByMobileAndOem(String mobileNo, String oemType) throws Exception {

        String sql = " SELECT * FROM t_merchant_info WHERE mobile_no = ? AND oem_type = ? ";
        return baseDao.findFirst(sql, new Object[]{mobileNo, oemType});
    }

    @Override
    public MerchantUser getMerObjectByMobileAndOem(String mobileNo, String oemType) throws Exception {
        String sql = " SELECT * FROM t_merchant_info WHERE mobile_no = ? AND oem_type = ? ";
        return baseDao.findFirst(MerchantUser.class, sql, new Object[]{mobileNo, oemType});
    }

    /**
     * 根据商户号获取代理商费率节点信息
     *
     * @param merchantNo
     * @param repayType
     * @return
     */
    @Override
    public Map<String, String> getAgentNodeFeeByMerNo(String merchantNo, String repayType) throws Exception {

        Map<String, String> resMap = new HashMap<>();
        JSONObject agentFeeRateJson = new JSONObject();
        JSONObject agentSingleFeeJson = new JSONObject();

        Map<String, Object> merInfoMap = getMerInfoByMerNo(merchantNo);
        if (null == merInfoMap || merInfoMap.isEmpty()) {
            return null;
        }
        String agentNode = StringUtil.filterNull(merInfoMap.get("agent_node"));
        String oemType = StringUtil.filterNull(merInfoMap.get("oem_type"));
        if (StringUtils.isEmpty(agentNode)) {
            return null;
        }
        String[] nodeArray = agentNode.split("-");
        if (nodeArray.length < 1) {
            return null;
        }
        String agentNo = "", agentFee = "", agentSingle = "";
        Map<String, Object> agentCostMap = null;

        for (int index = 0; index < nodeArray.length; index++) {

            agentNo = nodeArray[index];
            //获取代理商对应的服务成本
            agentCostMap = merFeeService.getMerFeeByMerNoAndOemType(Constants.MER_TYPE_AGENT, agentNo, oemType);

            if (agentCostMap == null || agentCostMap.isEmpty()) {
                return null;
            }

            switch (repayType) {
                case Constants.REPAY_TYPE_QUICK: {

                    agentFee = StringUtil.filterNull(agentCostMap.get("quick_fee_rate"));
                    agentSingle = StringUtil.filterNull(agentCostMap.get("quick_single_fee"));
                    break;
                }
                case Constants.REPAY_TYPE_PERFECT: {

                    agentFee = StringUtil.filterNull(agentCostMap.get("perfect_fee_rate"));
                    agentSingle = StringUtil.filterNull(agentCostMap.get("perfect_single_fee"));
                    break;
                }
                default: {
                    return null;
                }
            }
            agentFeeRateJson.put(agentNo, agentFee);
            agentSingleFeeJson.put(agentNo, agentSingle);
        }

        resMap.put("agentFeeRate", agentFeeRateJson.toJSONString());
        resMap.put("agentSingleFee", agentSingleFeeJson.toJSONString());
        return resMap;
    }

    /**
     * 修改商户认证状态
     *
     * @param merchantNo
     * @param realName
     * @param idCardNo
     * @param address
     * @param filePath
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int updateMerAuthInfo(String merchantNo, String realName, String idCardNo, String address, String filePath) throws Exception {

        String sql = " UPDATE t_merchant_info SET is_auth = ?, real_name = ?, id_card_no = ?, address = ?, file_path = ? WHERE merchant_no = ? ";
        return baseDao.execute(sql, new Object[]{Constants.MER_AUTH_STATUS_PASS, realName, idCardNo, address, filePath, merchantNo});
    }

    /**
     * 查询商户所属二级商户
     *
     * @param oemType
     * @param merchantNo
     * @return
     * @throws Exception
     */
    @Override
    public List<Map<String, Object>> getSubMerchant(String oemType, String merchantNo) throws Exception {
        String sql = " SELECT merchant_no merchantNo,merchant_name merchantName,mobile_no mobileNo,is_auth isAuth,mer_grade merGrade " +
                " FROM t_merchant_info WHERE oem_type = ? and parent_mer_no=? ";
        return baseDao.findList(sql, new Object[]{oemType, merchantNo});
    }

    @Override
    public MerchantUser getMerObjectByMerchantNoAndPwd(String oemType, String merchantNo, String loginPwd) throws Exception {
        String sql = " SELECT * FROM t_merchant_info WHERE oem_type = ? and merchant_no = ? AND login_pwd=? ";
        return baseDao.findFirst(MerchantUser.class, sql, new Object[]{oemType, merchantNo, loginPwd});
    }

    @Override
    public int updateMerchantLoginPwd(String oemType, String merchantNo, String newLoginPwd) throws Exception {
        String sql = " update t_merchant_info  set login_pwd=? WHERE oem_type = ? and merchant_no = ?  ";
        return baseDao.execute(sql, new Object[]{newLoginPwd, oemType, merchantNo});
    }

}
